/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.client.editor.controller;

import java.awt.event.ActionEvent;
import java.io.IOException;

import javax.swing.Action;
import javax.swing.text.BadLocationException;
import javax.swing.text.html.HTML;

import offset.nodes.client.editor.Editor;
import offset.nodes.client.editor.model.ListModel;
import offset.nodes.client.editor.model.Range;

/** Class for automatically creating bulleted lists from selected text
 */
public class ListActions {

    public static abstract class AbstractListAction extends EditorActions.AbstractEditorAction {

        public AbstractListAction(String name, Editor editor) {
            super(name, editor);
        }

        protected ListModel getModel(ActionEvent ae) {
            return new ListModel(getDocumentContext(ae));
        }
    }

    public static class ListInsertBreakAction extends AbstractListAction {

        public void action(ActionEvent e) throws Exception {
            int pos;
            int caretPosition = pos = getEditor(e).getCaretPosition();
            if (!(pos == 0 || getDocument(e).getText(pos - 1, 1).equals(" "))) {
                caretPosition++;
            }
            getModel(e).insertListItem(pos);
            getEditor(e).setCaretPosition(caretPosition);
        }

        public ListInsertBreakAction(Editor editor) {
            super("list-insert-break", editor);
        }
    }

    public static class ListTabAction extends AbstractListAction {

        protected Action defaultAction;

        public void action(ActionEvent e) throws BadLocationException, IOException {
            int start = getEditor(e).getSelectionStart();
            int end = getEditor(e).getSelectionEnd();
            ListModel model = getModel(e);

            if (start == end && !model.isStartOfListItem(start)) {
                defaultAction.actionPerformed(e);
                getEditor(e).setCaretPosition(start + 1);
            } else {
                model.indentRight(new Range(start, end));
                getEditor(e).setSelectionStart(start);
                getEditor(e).setSelectionEnd(end);
            }
        }

        public ListTabAction(Action defaultAction, Editor editor) {
            super("list-tab", editor);
            this.defaultAction = defaultAction;
        }
    }

    public static class ListBackTabAction extends AbstractListAction {

        public void action(ActionEvent e) throws BadLocationException, IOException {
            int start;
            int end;
            getModel(e).indentLeft(new Range(start = getEditor(e).getSelectionStart(), end = getEditor(e).getSelectionEnd()));
            getEditor(e).setSelectionStart(start);
            getEditor(e).setSelectionEnd(end);
        }

        public ListBackTabAction(Editor editor) {
            super("list-back-tab", editor);
        }
    }

    public static class ListDeletePrevCharAction extends AbstractListAction {

        Action defaultAction;

        public void action(ActionEvent e) throws Exception {
            ListModel model = getModel(e);
            int pos = getEditor(e).getCaretPosition();

            if (model.isStartOfListItem(pos)) {
                if (model.isFirstListItem(pos)) {
                    if (model.isEmptyListItem(pos)) {
                        if (model.isLastListItem(pos)) {
                            if (getDocument(e).getLength() == pos) {
                                model.listItemsToParagraphs(new Range(getEditor(e).getSelectionStart(), getEditor(e).getSelectionEnd()));
                            } else {
                                model.removeList(pos);
                            }
                        } else {
                            model.removeListItem(pos);
                        }
                    }
                } else {
                    model.listItemToListParagraph(pos);
                }
                getEditor(e).setCaretPosition(pos);
            } else if (model.isStartOfListItemParagraph(pos)) {
                model.mergeListItemParagraph(pos);
                getEditor(e).setCaretPosition(Math.max(0, pos - 1));
            } else {
                defaultAction.actionPerformed(e);
            }
        }

        public ListDeletePrevCharAction(Action defaultAction, Editor editor) {
            super("list-delete-previous", editor);
            this.defaultAction = defaultAction;
        }
    }

    public static class ToggleListAction extends AbstractListAction {

        HTML.Tag listTag;

        public ToggleListAction(HTML.Tag listTag, Editor editor) {
            super("", editor);
            this.listTag = listTag;
            if (listTag.equals(HTML.Tag.OL)) {
                setIcon(new javax.swing.ImageIcon(getClass().getResource("/offset/nodes/client/editor/view/resources/sc_defaultnumbering.png")));
                setName(java.util.ResourceBundle.getBundle("offset/nodes/client/editor/view/resources/EditorBundle").getString("Numbered_list"));
            } else if (listTag.equals(HTML.Tag.UL)) {
                setIcon(new javax.swing.ImageIcon(getClass().getResource("/offset/nodes/client/editor/view/resources/sc_defaultbullet.png")));
                setName(java.util.ResourceBundle.getBundle("offset/nodes/client/editor/view/resources/EditorBundle").getString("Bullet_list"));
            }
        }

        public void action(ActionEvent ae) throws Exception {
            Range range;
            getModel(ae).toggleListParagraphs(range = new Range(getEditor(ae).getSelectionStart(), getEditor(ae).getSelectionEnd()), listTag);
            refreshCaret(ae, range);
        }
    }
}
